package sm2_test1

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/tjfoc/gmsm/sm2"
	"math/big"
)

// 声明公钥和私钥（用实际的 SM2 密钥对替换）
const (
	privateKeyHex = "A4D26EB87389B471D576E47B7D92DC9A0686086DDB5DF1876EA8E68755E0FC42"
	publicKeyHex  = "B96F5A7C87D14E93F0BA762C332F64EC4DCBD81745073C38CADCD4A92406409B3BAB19599A393C3736AE61C5716D959BC9CA0387E48012AA6C474293BB046E37"
)

func Start() {
	// 解析私钥
	privKey, err := parseSM2PrivateKey(privateKeyHex)
	if err != nil {
		fmt.Println("Failed to parse private key:", err)
		return
	}

	// 解析公钥
	pubKey, err := parseSM2PublicKey(publicKeyHex)
	if err != nil {
		fmt.Println("Failed to parse public key:", err)
		return
	}

	// 假设的 userId
	userId := []byte("00000001")
	fmt.Println("userId:", hex.EncodeToString(userId))

	// 假设的 sourceData
	//sourceData := []byte("384987850874299414b5d91fea6015230dac1368")
	sourceData, err := hex.DecodeString("384987850874299414b5d91fea6015230dac1368")
	if err != nil {
		fmt.Println("Failed to hex.DecodeString for sourceData:", err)
		return
	}

	// 签名
	signature, err := Sign(sourceData, userId, privKey)
	if err != nil {
		fmt.Println("Failed to sign:", err)
		return
	}
	//signature = []byte("0750FAFB7D6C13E517F2B3944B004F69B05D11093553265D332F546F020319015D3E0E0A3D6EBB05FA0B145AFF0DBAF9D36A184E8EC62F6B01B55A8237CB43FF")
	//signature, err = hex.DecodeString("8AFBE838C1E23436D2472535799AD1CA5A5EAA2212450413CF8CD0B8306E16F1A8AB9FB852E9C2393CAE6432811615811C7571EEB6C4BE02020F37AFCE02D4DC")
	//if err != nil {
	//	fmt.Println("Failed to hex.DecodeString for signature:", err)
	//	return
	//}

	fmt.Println("Signature:", hex.EncodeToString(signature))

	// 验证签名
	isValid, err := VerifySignature(sourceData, userId, signature, pubKey)
	if err != nil {
		fmt.Println("Failed to verify signature:", err)
		return
	}

	if isValid {
		fmt.Println("Signature is valid.")
	} else {
		fmt.Println("Signature is invalid.")
	}
}

// parseSM2PrivateKey 解析SM2私钥
func parseSM2PrivateKey(privateKeyHex string) (*sm2.PrivateKey, error) {
	privateKeyBytes, err := hex.DecodeString(privateKeyHex)
	if err != nil {
		return nil, err
	}
	d := new(big.Int).SetBytes(privateKeyBytes)
	curve := sm2.P256Sm2()
	priv := new(sm2.PrivateKey)
	priv.D = d
	priv.PublicKey.Curve = curve
	priv.PublicKey.X, priv.PublicKey.Y = curve.ScalarBaseMult(d.Bytes())
	return priv, nil
}

// parseSM2PublicKey 解析SM2公钥
func parseSM2PublicKey(publicKeyHex string) (*sm2.PublicKey, error) {
	publicKeyBytes, err := hex.DecodeString(publicKeyHex)
	if err != nil {
		return nil, err
	}
	x := new(big.Int).SetBytes(publicKeyBytes[:32])
	y := new(big.Int).SetBytes(publicKeyBytes[32:])
	pub := &sm2.PublicKey{
		Curve: sm2.P256Sm2(),
		X:     x,
		Y:     y,
	}
	return pub, nil
}

// Sign 使用SM2算法对数据进行签名
func Sign(data, userId []byte, privKey *sm2.PrivateKey) ([]byte, error) {
	// 计算 SHA-1 摘要
	hash := sha1.Sum(data)
	digest := hash[:]

	fmt.Printf("Digest for signing: %x\n", digest)

	// 调用 SM2 的 Sign 方法
	r, s, err := sm2.Sm2Sign(privKey, digest, userId, rand.Reader)
	if err != nil {
		return nil, fmt.Errorf("failed to sign: %w", err)
	}

	fmt.Printf("Signature R: %x\n", r)
	fmt.Printf("Signature S: %x\n", s)

	// 将 R 和 S 拼接为签名
	rBytes := r.Bytes()
	sBytes := s.Bytes()
	signature := make([]byte, 64)
	copy(signature[32-len(rBytes):32], rBytes)
	copy(signature[64-len(sBytes):], sBytes)
	return signature, nil
}

// VerifySignature 使用SM2算法验证签名
func VerifySignature(data, userId []byte, signature []byte, pubKey *sm2.PublicKey) (bool, error) {
	// 分离 R 和 S
	r := new(big.Int).SetBytes(signature[:32])
	s := new(big.Int).SetBytes(signature[32:])

	fmt.Printf("Signature R for verification: %x\n", r)
	fmt.Printf("Signature S for verification: %x\n", s)

	// 计算 SHA-1 摘要
	hash := sha1.Sum(data)
	digest := hash[:]

	fmt.Printf("Digest for verification: %x\n", digest)

	// 验证签名
	return sm2.Sm2Verify(pubKey, digest, userId, r, s), nil
}
